<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        div{
            width: 100px;
            height: 100px;
            background: pink;
            position: fixed;
        }
    </style>
</head>
<body>
    <div></div>


    <script src="../../../tools.js"></script>
    <script>
        const oDiv = document.querySelector('div');
        oDiv.addEventListener('click' , function(){
            move( oDiv , {left:500 , top:500} , function(){console.log('运动停止了')});
        })





        /*
            运动函数: 
                核心功能: 
                    1, 让css属性的改变,不是瞬间完成,是逐步完成的
                       视觉效果,类似于运动效果

                    2, 当运动结束时,可以执行相应的程序内容
                       第三个参数 赋值的函数

            函数的封装
        
        */

        // 参数1: 运动的标签对象
        // 参数2: 运动的css属性和属性值,必须是对象形式
        // 参数3: 运动结束,执行的程序 --- 回调函数 默认值 是空函数
        function move( ele , moveObj , callback = function(){} ){
            // 1, 定义一个变量,存储生成 定时器的个数
            let num = 0;
            // 定义变量,存储定时器
            // 也可以在 循环中直接定义
            // 只要是 let 声明的变量,每次循环,都会在不同作用域中,生成不同的变量,存储不同的数据
            // 直接定义在循环里面,还是定义在循环外,在循环内赋值,都可以
            // let time;

            // 2, 循环遍历参数2,每次循环,生成一个定时器
            // 声明定义循环变量,必须使用let,let可以生成不同作用域的循环变量
            // 存储不同的 type 属性 也就是 运动的css的属性
            for(let type in moveObj){
                // 没循环一次,生成一个定时器,变量执行自增,累加1
                num++;

                // 判断,type属性是 opacity 透明度 
                // 将 目标数值 也就是 moveObj参数2 中存储数值*100
                if(type === 'opacity'){
                    moveObj[type] *= 100;
                }


                // 生成定时器
                let time = setInterval(function(){
                    // (1), 获取标签对象,当前属性的原始值
                    // 兼容透明度: 是透明度 直接获取属性值,结果*100   
                    //           不是透明度 获取属性值,取整
                    let oldVal = type === 'opacity' ? myGetStyle(ele,type)*100 : parseInt(myGetStyle(ele,type));

                    // (2), 计算步长
                    // (最终数值 - 初始数值 ) / 自定义的次数
                    let speed = ( moveObj[type] - oldVal ) / 10;

                    // (3), 步长取整
                    // 步长大于0 向上取整  步长小于0 向下取整
                    speed = speed > 0 ? Math.ceil( speed ) : Math.floor( speed );

                    // (4), 初始值 累加 步长
                    oldVal += speed;

                    // (5), 将改变的初始值 赋值给 标签对象,当前css属性
                    // 兼容透明度: 是透明度 初始数值/100 
                    //           不是透明度 初始数值 拼接 px单位
                    ele.style[type] = type === 'opacity' ? oldVal/100 : oldVal + 'px';

                    // (6), 判断 初始数值 是否 等于 最终数值
                    if( oldVal === moveObj[type] ){
                        // 清除定时器
                        clearInterval(time);
                        // 计数器变量--
                        num--;
                        // 计数器数值为0 时
                        // 就是多有的定时器都被清除了,运动停止结束了
                        if(num === 0){
                            // 执行 参数3 输入的 回调函数
                            callback();
                        }
                    }

                } , 20)
            }

        }


        /*
            步骤:
                1, 定义变量,存储定时器个数
                2, 循环遍历参数2
                    2-1 定期器个数++
                    2-2 判断 属性是透明度 最终数值*100
                    2-3 生成定期器,执行运动效果
                        2-3-1, 获取初始数值
                            兼容透明度: 是透明度 直接获取结果*100
                                      不是透明度 获取结果取整

                        2-3-2  计算步长
                            ( 最终数值 - 初始数值 ) / 自定义次数
                                次数越大运动时间越短
                                
                        2-3-3  步长取整
                            步长 > 0     向上取整
                                否则     向下取整

                        2-3-4  初始数值 累加步长

                        2-3-5  赋值 改变的 初始数值 给 标签对象当前css属性
                            兼容透明度: 是透明度  初始数值/100
                                      不是透明度  初始数值 拼接 px单位

                        2-3-6  判断 初始数值 是否 等于 最终数值
                            当 初始数值 等予 最终数值 
                                清除定时器
                                定时器个数--
                                判断
                                    如果定时器 个数 === 0
                                    所有定时器已经被清除 运动已经停止 
                                    调用 参数3 回调函数
        
        
        
        */
    </script>
</body>
</html>